iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
Mobile Development

Flutter 30: from start to store系列 第 19

Flutter介紹:把資料存進手機 - app database

  • 分享至 

  • xImage
  •  

在APP做了許多操作後,當然不希望辛苦操作完的資料在關閉APP就通通不見了。
今天要一起來看看如何在flutter app中透過建立SQLite的資料庫來保存資料。

好的,那我們就開始吧!


加入sqflitepath套件

  • 加入sqflite, path
    $ flutter pub add sqflite path
    
    $ flutter pub get
    

定義data model

  • 比如說我們要儲存「Dog」相關的資料,要先建立「Dog」的資料模型
    class Dog {
      final int id;
      final String name;
      final int age;
    
      const Dog({
        required this.id,
        required this.name,
        required this.age,
      });
    }
    

啟動資料庫

  • 建立資料庫連結

    // WidgetFlutterBinding 用於將flutter framework和flutter引擎連結,確定兩者連結後,準備要透過widget層的方法調用原生api來開啟資料庫
    WidgetsFlutterBinding.ensureInitialized();
    
    final database = openDatabase( // 開啟一個資料庫
      join(await getDatabasesPath(), 'doggie_database.db'), 
    );
    
  • sqflitegetDatabasePath()方法可以取得該資料庫的位置,而doggie_database.db是該資料庫的檔案名稱。兩者透過path提供的join方法連接起來,就是該資料庫的資源位置。


創建table

  • 和開好的db連線後,要在該db創建table
    final database = openDatabase(
      join(await getDatabasesPath(), 'doggie_database.db'),
    
      onCreate: (db, version) { // 第一次開啟db時,執行以下指令
        return db.execute(
          'CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)', // 創建含有id, name, age欄位的table,名稱為dogs
        );
      },
      version: 1, // 做資料庫版控用
    );
    

新增資料:CREATE

  • 要建立一筆Dog資料,並存進table,首先要將Dog物件實例改成Map形式
    class Dog {
      final int id;
      final String name;
      final int age;
    
      const Dog({
        required this.id,
        required this.name,
        required this.age,
      });
    
      Map<String, dynamic> toMap() {
        return {
          'id': id,
          'name': name,
          'age': age,
        };
      }
    }
    
    Dog class建立toMapmethod
  • 定義一個insertDog function,內部透過db.insert(tableName, data, conflictAlgorithm)寫入資料
    Future<void> insertDog(Dog dog) async {
      final db = await database;
    
      await db.insert(
        'dogs', // dogs table
        dog.toMap(), // 要寫入的資料
        conflictAlgorithm: ConflictAlgorithm.replace, // 定義資料衝突規則:若有衝突則覆蓋原先資料
      );
    }
    
  • 新增資料的範例:
    var fido = const Dog(
      id: 0,
      name: 'Fido',
      age: 35,
    ); // 建立名為'Fido'的狗的資料
    
    await insertDog(fido); // 使用上述定義的function將狗的資料存進db
    

讀取資料:READ

  • 首先定義讀取讀取狗的資料的function:selectAllDogs
    Future<List<Dog>> queryAllDogs() async {
      final db = await database;
    
      final List<Map<String, dynamic>> maps = await db.query('dogs'); // 取得'dogs' table的所有資料
    
      return List.generate(maps.length, (i) {
        return Dog(
          id: maps[i]['id'],
          name: maps[i]['name'],
          age: maps[i]['age'],
        );
      }); // 將所有取得的狗的資料轉換為Dog物件的列表
    }
    
    
  • 讀取資料的範例:
    List<Dog> allDogs = await queryAllDogs();
    
  • 在設定篩選條件時,可以使用
    • rawQuery
      db.rawQuery('SELECT * FROM "table"'); // 使用raw SQL
      
    • query(tableName, columns, where, whereArgs)
      db.query(
          'table', // table 名稱
          columns: ['group'], // 要選取的欄位
          where: '"group" = ?',  // 篩選條件
          whereArgs: ['my_group'] // 要求篩選的參數
      );
      

更新資料:UPDATE

  • 找到要更新的資料並轉換成Map,透過wherewhereArgs來指定要查詢的目標並更新
    Future<void> updateDog(Dog dog) async {
      final db = await database;
    
      await db.update(
        'dogs', // table名稱
        dog.toMap(), // 新的資料
        where: 'id = ?', // 查詢的條件:以id查詢
        whereArgs: [dog.id], // 該狗狗的id
      );
    }
    
  • 更新資料實例
    fido = Dog(
      id: fido.id,
      name: fido.name,
      age: fido.age + 7, // Fido的年齡有所變化
    );
    await updateDog(fido); // 依照id找到並更新Fido的資料
    

刪除資料:DELETE

  • 同「更新資料」,以wherewhereArgs作為查詢條件
    Future<void> deleteDog(int id) async {
      final db = await database;
    
      await db.delete(
        'dogs',
        where: 'id = ?', // 以id作為查詢條件
        whereArgs: [id], // 刪除此id
      );
    }
    
  • 刪除資料範例:
    await deleteDog(fido.id);
    

Recap

今天看到操作資料庫有以下幾個要點:

  • 資料庫的連接
    final database = openDatabase(
      join(await getDatabasesPath(), DB_NAME),
    
      onCreate: (db, version) { 
        return db.execute(
          RAW_SWL,
        );
      },
      version: VERSION_NUMBER,
    )
    
  • 新增資料:db.insert(tableName, data)
  • 讀取資料:db.query(tableName, column, where, whereArgs)
  • 修改資料:db.update(tableName, data, where, whereArgs)
  • 刪除資料:db.delete(tableName, where, whereArgs)

成功將我們的資料存進資料庫後並確認重開時可以正常讀取後,我們明天要來對APP進行最後的修整囉~


上一篇
Flutter介紹:新增別人寫好的酷炫功能 - flutter package
下一篇
Flutter介紹:完整你的Flutter專案
系列文
Flutter 30: from start to store30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言